package com.agua.enturno.vista.util;

import com.agua.enturno.excepciones.ExcepcionDeReglaDelNegocio;
import com.agua.enturno.servicios.AgendaService;
import com.agua.enturno.vista.dto.AgendaDTO;
import com.agua.enturno.vista.dto.SemanaDTO;
import org.apache.wicket.injection.Injector;
import org.apache.wicket.model.IModel;
import org.apache.wicket.spring.injection.annot.SpringBean;
import org.joda.time.Interval;
import org.joda.time.LocalDate;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public class SemanasIterator implements Serializable {

	private static final long serialVersionUID = 1L;

	@SpringBean
    private AgendaService agendaService;
    
    private IModel<AgendaDTO> agendaModel;
    private LocalDate lunesInicial;
    private List<SemanaDTO> semanas = new ArrayList<SemanaDTO>();
    
    private int indiceDeSemanaActual = 0;
    
    /*------------------------------------ Constructors ------------------------------------*/

    public SemanasIterator(IModel<AgendaDTO> agendaModel, LocalDate lunesInicial) {
    	Injector.get().inject(this);
    	
    	this.lunesInicial = lunesInicial;
    	this.agendaModel = agendaModel;
    	this.recargarHorarios();
    	this.reset();
	}

    /*--------------------------------------------------------------------------------------*/
    /*------------------------------------ Public methods ----------------------------------*/

    public SemanaDTO getSemanaActual() {
		return this.semanas.get(indiceDeSemanaActual);
	}
    
    public boolean haySiguiente() {
    	return indiceDeSemanaActual + 1 < semanas.size();
    }
    
    public boolean hayAnterior() {
    	return indiceDeSemanaActual > 0;
    }
    
    public void siguiente() {
   		indiceDeSemanaActual++;
    }
    
    public void anterior() {
   		indiceDeSemanaActual--;
    }
    
    public void reset() {
    	this.indiceDeSemanaActual = 0;
    }
    
    public void recargarHorarios() {
    	
    	int cantidadDeSemanas = agendaModel.getObject().getAntelacionMaxima().toStandardDays().getDays() / 7 + 1;
    	
    	semanas.clear();
    	for (int i = 0; i < cantidadDeSemanas; i++) 
    		semanas.add(agendaService.findHorariosByWeek(agendaModel.getObject().getId(), lunesInicial.plusWeeks(i)));
    }
    
    public void setFecha(LocalDate fecha) throws ExcepcionDeReglaDelNegocio {
    	
    	if (!fechaEstaEnRango(fecha)) 
			throw new ExcepcionDeReglaDelNegocio("La fecha seleccionada no se encuentra dentro del período de antelación permitido para la agenda");
    	
    	indiceDeSemanaActual = calcularIndice(fecha);
    }

    /*--------------------------------------------------------------------------------------*/
    /*----------------------------------- Private methods ----------------------------------*/

	private int calcularIndice(LocalDate fecha) {
		
		int indice = indiceDeSemanaActual;
		
		for (int i = 0; i < semanas.size(); i++) {
			
			if (semanas.get(i).contieneLaFecha(fecha)) {
				indice = i;
				break;
			}
		}

		return indice;
	}

	private boolean fechaEstaEnRango(LocalDate fecha) {
		
		Interval rango = new Interval(lunesInicial.toDateTimeAtStartOfDay(), lunesInicial.plus(agendaModel.getObject().getAntelacionMaxima()).toDateTimeAtStartOfDay());
		return rango.contains(fecha.toDateTimeAtStartOfDay());
	}
	
    /*--------------------------------------------------------------------------------------*/

}
